/**  
 * All rights Reserved, Designed By www.tydic.com
 * @Title:  HttpClient.java   
 * @Package com.axin.common.httpclient   
 * @Description:    TODO(用一句话描述该文件做什么)   
 * @author: axin     
 * @date:   2019年3月9日 下午11:17:35   
 * @version V1.0 
 * @Copyright: 2019 www.hao456.top Inc. All rights reserved. 
 */
package com.axin.common.huobi;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

import javax.annotation.Resource;
import javax.xml.bind.DatatypeConverter;

import org.apache.commons.lang3.StringUtils;

import com.axin.common.entity.ApiToken;
import com.axin.common.exception.ApiException;
import com.axin.common.utils.JsonUtil;
import com.fasterxml.jackson.core.type.TypeReference;

import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**   
 * @Description: TODO 
 * @ClassName:  HttpClient
 * @author:  Axin 
 * @date:   2019年3月9日 下午11:17:35   
 * @Copyright: 2019 www.hao456.top Inc. All rights reserved. 
 */
public class HttpRequest {
	
	    private String API_URL;
	    
	    @Resource
	    private OkHttpClient okHttpClient;
	    

		/**
		 * @param aPI_URL the aPI_URL to set
		 */
		public void setAPI_URL(String aPI_URL) {
			API_URL = aPI_URL;
		}

	public <T> T get(ApiToken token,String uri, Map<String, String> params, TypeReference<T> ref) {
        if (params == null) {
            params = new HashMap<>();
        }
        return call(token, "GET", uri, null, params, ref);
    }

    // send a POST request.
	public <T> T post(ApiToken token,String uri, Object object, TypeReference<T> ref) {
        return call(token,"POST", uri, object, new HashMap<String, String>(), ref);
    }

    // call api by endpoint.
    <T> T call(ApiToken token, String method, String uri, Object object, Map<String, String> params,
               TypeReference<T> ref) {
        ApiSignature sign = new ApiSignature();
        String API_HOST = getHost();
        sign.createSignature(token.getAccessKeyId(), token.getAccessKeySecret(), method, API_HOST, uri, params);
        try {
            Request.Builder builder = null;
            if ("POST".equals(method)) {
            	MediaType JSON = MediaType.parse("application/json");
                RequestBody body = RequestBody.create(JSON, JsonUtil.writeValue(object));
                builder = new Request.Builder().url(API_URL + uri + "?" + toQueryString(params)).post(body);
            } else {
                builder = new Request.Builder().url(API_URL + uri + "?" + toQueryString(params)).get();
            }
            if (StringUtils.isNotEmpty(token.getAssetPassword())) {
                builder.addHeader("AuthData", authData(token.getAssetPassword()));
            }
            Request request = builder.build();
            Response response = okHttpClient.newCall(request).execute();
            String s = response.body().string();
            //System.out.println(s);
            return JsonUtil.readValue(s, ref);
        } catch (IOException e) {
            throw new ApiException(e);
        }
    }

    String authData(String assetPassword) {
        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
        md.update(assetPassword.getBytes(StandardCharsets.UTF_8));
        md.update("hello, moto".getBytes(StandardCharsets.UTF_8));
        Map<String, String> map = new HashMap<>();
        map.put("assetPwd", DatatypeConverter.printHexBinary(md.digest()).toLowerCase());
        try {
            return ApiSignature.urlEncode(JsonUtil.writeValue(map));
        } catch (IOException e) {
            throw new RuntimeException("Get json failed: " + e.getMessage());
        }
    }

    // Encode as "a=1&b=%20&c=&d=AAA"
    String toQueryString(Map<String, String> params) {
        return String.join("&", params.entrySet().stream().map((entry) -> {
            return entry.getKey() + "=" + ApiSignature.urlEncode(entry.getValue());
        }).collect(Collectors.toList()));
    }

    
    private String getHost() {
        String host = null;
        try {
            host = new  URL(API_URL).getHost();
        } catch (MalformedURLException e) {
            System.err.println("parse API_URL error,system exit!,please check API_URL:" + API_URL ); 
            System.exit(0);
        }
        return host;
    }
	

}
